package com.javaking.clanteam.studentutils.sql;

import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;

import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.preference.PreferenceManager;
import android.provider.BaseColumns;
import android.util.Log;
import android.widget.Toast;

import com.javaking.clanteam.calendar.provider.CalendarContract.Events;
import com.javaking.clanteam.studentutils.courses.CourseData;

public class CourseHelper extends SQLiteOpenHelper implements BaseColumns{
	
	public static final int DATABASE_VERSION = 2;
	public static final String DATABASE_NAME = "course.db";
	
	public static final String COURSE_TABLE_NAME = "course";
	public static final String COLUMN_ID = _ID;
	public static final String COLUMN_CREATE_DATE = "created";
	public static final String COLUMN_COURSE_TITLE = "course";
	public static final String COLUMN_TEACHER = "teacher";
	public static final String COLUMN_ROOM = "room";
	public static final String COLUMN_TIMES = "times";
	public static final String COLUMN_PERIOD = "period";
	public static final String COLUMN_ASSIGNMENT_IDS = "assignments";
	
	public static final String COURSE_TABLE_CREATE = "CREATE TABLE "
			+ COURSE_TABLE_NAME + " ( "
			+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
			+ COLUMN_CREATE_DATE + " INTEGER DEFAULT ( strftime('%s','now')*1000),"
			+ COLUMN_COURSE_TITLE + " TEXT NOT NULL,"
			+ COLUMN_TEACHER + " TEXT,"
			+ COLUMN_ROOM + " TEXT,"
			+ COLUMN_TIMES + " TEXT,"
			+ COLUMN_PERIOD + " INTEGER DEFAULT -1,"
			+ COLUMN_ASSIGNMENT_IDS + " TEXT"
			+ ");";
	
	private Context mContext;

	public CourseHelper(Context context) {
		super(context,DATABASE_NAME	,null,DATABASE_VERSION);
		
		mContext = context;
	}
	
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(COURSE_TABLE_CREATE);
		Log.i("tag", "Course Table Created");
	}

	/**
	 * For now we will just drop the table and add it again.
	 */
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

		// TODO Make this more efficient/preserve data.
		
		
		// Logs that the database is being upgraded
        Log.w("course", "Upgrading database from version " + oldVersion + " to "
                + newVersion + ", which will destroy all old data");

        db.execSQL("DROP TABLE IF EXISTS "+COURSE_TABLE_NAME);
        
        onCreate(db);
	}
	
	/**
	 * Attempts to return a <code>CourseData</code> that has the same title as
	 * <code>courseName</code>.
	 * @param courseName
	 * @return The {@link CourseData} if it exists or null if it doesn't. <br/>
	 * 		NOTE: If there are more than one course with the same title, this method will
	 * 		only return the one added first.
	 */
	public CourseData getCourseByName(String courseName) {
		SQLiteDatabase db = getWritableDatabase();
		Cursor cursor = db.query(COURSE_TABLE_NAME, null,
				COLUMN_COURSE_TITLE + "=?", new String[]{courseName},
				null, null, null);
		CourseData course = CourseData.getCourseFromCursor(cursor);
		cursor.close();
		db.close();
		return course;
	}
	
	public CourseData getCourseById(String id) {
		SQLiteDatabase db = getWritableDatabase();
		Cursor cursor = db.query(COURSE_TABLE_NAME, null,
				COLUMN_ID + "=?", new String[]{id},
				null, null, null);
		CourseData course = CourseData.getCourseFromCursor(cursor);
		cursor.close();
		db.close();
		return course;
	}
	
	
	public CourseData[] getAllCourses() {
		SQLiteDatabase db = getWritableDatabase();
		Cursor cursor = db.query(COURSE_TABLE_NAME, null, null, null, null, null, null);
		CourseData[] courses = CourseData.getAllCourseFromCursor(cursor);
		Arrays.sort(courses, new Comparator<CourseData>() {

			@Override
			public int compare(CourseData lhs, CourseData rhs) {
				try {
					int lId = Integer.parseInt(lhs.getId());
					int rId = Integer.parseInt(rhs.getId());
					return lId-rId;
				} catch (NumberFormatException e) {
					return 0;
				}
			}
			
		});
		cursor.close();
		db.close();
		return courses;
	}
	
	public void addCourse(CourseData course) {
		SQLiteDatabase db = getWritableDatabase();
		String id = String.valueOf(db.insert(COURSE_TABLE_NAME,
				null, course.convertToContentValues()));
		try {
			course.setId(id);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		db.close();
		
		addCourseToCal(course);
		
		Toast.makeText(mContext, String.format("Added course:%s",course.getCourseTitle()), Toast.LENGTH_LONG).show();
	}
	
	public void addCourseToCal(CourseData course) {
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
		if (prefs.getBoolean("addToCal", false)) {
			long startDate = prefs.getLong("startDate", Calendar.getInstance().getTimeInMillis());
			long endDate = prefs.getLong("endDate", Calendar.getInstance().getTimeInMillis());
			
			Events.RRuleBuilder builder = new Events.RRuleBuilder();
			if ((endDate-startDate)<1000*60*60*24) { // if the times are within a day
				Toast.makeText(mContext, "Start and end dates for term within a day\nDefaulting to 25 week term", Toast.LENGTH_LONG).show();
				builder.setCount(25);
			} else {
				Calendar cal = Calendar.getInstance();
				cal.setTimeInMillis(endDate);
				builder.setUntil(cal.getTime());
			}
			
			builder.setFreq(Events.RRuleBuilder.Frequencies.WEEKLY);
			String calId = prefs.getString("useCalendar", "1");
			ContentValues cv = CourseData.courseToEventValues(course, calId);
			
			cv.put(Events.RRULE, builder.buildRRule());
			
			mContext.getContentResolver().insert(Events.CONTENT_URI, cv);
		}
	}
	
	public int dropCourseByTitle(String courseTitle) {
		SQLiteDatabase db = getWritableDatabase();
		int affectRows = db.delete(COURSE_TABLE_NAME, COLUMN_COURSE_TITLE+"=?", new String[] {courseTitle});
		db.close();
		Toast.makeText(mContext, String.format("Dropped course:%s",courseTitle), Toast.LENGTH_LONG).show();
		return affectRows;
	}
	
	public int dropCourse(CourseData course) {
		String id = course.getId();
		if (id==null) {
			return dropCourseByTitle(course.getCourseTitle());
		} else {
			return dropCourseById(id,course.getCourseTitle());
		}
	}
	
	public int dropCourseById(String id,String courseTitle) {
		SQLiteDatabase db = getWritableDatabase();
		int affectRows = db.delete(COURSE_TABLE_NAME, COLUMN_ID+"=?", new String[] {id});
		db.close();
		Toast.makeText(mContext, String.format("Dropped course:%s",courseTitle), Toast.LENGTH_LONG).show();
		return affectRows;
	}

	public void updateCourse(CourseData oldCourse, CourseData newCourse) {
		SQLiteDatabase db = getWritableDatabase();
		String whereClause = COLUMN_ID+"=?";
		db.update(COURSE_TABLE_NAME, newCourse.convertToContentValues(),
				whereClause, new String[]{oldCourse.getId()});
		db.close();
	}
	
	public void purgeTable() {
		// Logs that the database is being upgraded
        Log.w("course", "Recreating the table by droping it and then" +
        		"recreating it.");

        SQLiteDatabase db = getWritableDatabase();
        
        db.execSQL("DROP TABLE IF EXISTS "+COURSE_TABLE_NAME);
        
        onCreate(db);
        
        db.close();
	}

}
